home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
symbol.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
65KB
|
1,763 lines
// $Id: symbol.cpp,v 1.11 1999/03/09 14:37:17 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler Open
// Source License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <sys/stat.h>
#include <assert.h>
#include "stream.h"
#include "control.h"
#include "ast.h"
#include "semantic.h"
#include "table.h"
#include "zip.h"
#if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
#include <dirent.h>
#elif defined(WIN32_FILE_SYSTEM)
#include <windows.h>
#endif
char *FileSymbol::java_suffix = StringConstant::U8S__DO_java;
int FileSymbol::java_suffix_length = strlen(java_suffix);
char *FileSymbol::class_suffix = StringConstant::U8S__DO_class;
int FileSymbol::class_suffix_length = strlen(class_suffix);
bool MethodSymbol::IsFinal()
{
return ((AccessFlags *) this) -> ACC_FINAL() || ((AccessFlags *) this) -> ACC_PRIVATE() || containing_type -> ACC_FINAL();
}
wchar_t *MethodSymbol::Header(Semantic *sem, LexStream::TokenIndex token_location)
{
if (! this -> IsTyped())
this -> ProcessMethodSignature(sem, token_location);
if (! header)
{
bool is_constructor = false;
for (MethodSymbol *constr = containing_type -> FindConstructorSymbol(); constr; constr = constr -> next_method)
{
if (this == constr)
{
is_constructor = true;
break;
}
}
int length = this -> Type() -> ContainingPackage() -> PackageNameLength() +
this -> Type() -> ExternalNameLength() +
(is_constructor ? containing_type -> NameLength() : this -> NameLength()) + 5; // '/' after package_name
// ' ' after type
// '(' after name
// ')' after all parameters
// ';' to terminate
for (int i = 0; i < NumFormalParameters(); i++)
{
VariableSymbol *formal = FormalParameter(i);
length += (formal -> Type() -> ContainingPackage() -> PackageNameLength() +
formal -> Type() -> ExternalNameLength() +
formal -> NameLength() + 4); // '/' after package_name
// ' ' after type
// ',' and ' ' to separate this formal parameter from the next one
}
header = new wchar_t[length + 1]; // +1 for '\0'
wchar_t *s = header;
if (is_constructor)
{
for (wchar_t *s2 = this -> containing_type -> Name(); *s2; s2++)
*s++ = *s2;
}
else
{
PackageSymbol *package = this -> Type() -> ContainingPackage();
wchar_t *package_name = package -> PackageName();
if (package -> PackageNameLength() > 0 && wcscmp(package_name, StringConstant::US__DO_) != 0)
{
while (*package_name)
{
*s++ = (*package_name == U_SLASH ? (wchar_t) U_DOT : *package_name);
package_name++;
}
*s++ = U_DOT;
}
for (wchar_t *s2 = this -> Type() -> ExternalName(); *s2; s2++)
*s++ = *s2;
*s++ = U_SPACE;
for (wchar_t *s3 = Name(); *s3; s3++)
*s++ = *s3;
}
*s++ = U_LEFT_PARENTHESIS;
if (NumFormalParameters() > 0)
{
for (int k = 0; k < NumFormalParameters(); k++)
{
VariableSymbol *formal = FormalParameter(k);
PackageSymbol *package = formal -> Type() -> ContainingPackage();
wchar_t *package_name = package -> PackageName();
if (package -> PackageNameLength() > 0 && wcscmp(package_name, StringConstant::US__DO_) != 0)
{
while (*package_name)
{
*s++ = (*package_name == U_SLASH ? (wchar_t) U_DOT : *package_name);
package_name++;
}
*s++ = U_DOT;
}
for (wchar_t *s2 = formal -> Type() -> ExternalName(); *s2; s2++)
*s++ = *s2;
*s++ = U_SPACE;
for (wchar_t *s3 = formal -> Name(); *s3; s3++)
*s++ = *s3;
*s++ = U_COMMA;
*s++ = U_SPACE;
}
s -= 2; // remove the last ',' and ' '
}
*s++ = U_RIGHT_PARENTHESIS;
*s++ = U_SEMICOLON;
*s = U_NULL;
assert((s - header) <= length);
}
return header;
}
MethodSymbol *SymbolTable::FindOverloadMethod(MethodSymbol *base_method, AstMethodDeclarator *method_declarator)
{
for (MethodSymbol *method = base_method; method; method = method -> next_method)
{
assert(method -> IsTyped());
if (method -> NumFormalParameters() == method_declarator -> NumFormalParameters())
{
int i;
for (i = method -> NumFormalParameters() - 1; i >= 0; i--)
{
AstFormalParameter *parameter = method_declarator -> FormalParameter(i);
if (method -> FormalParameter(i) -> Type() != parameter -> parameter_symbol -> Type())
break;
}
if (i < 0)
return method;
}
}
return(MethodSymbol *) NULL;
}
void TypeSymbol::ProcessTypeHeaders()
{
AstClassDeclaration *class_declaration = declaration -> ClassDeclarationCast();
if (class_declaration)
semantic_environment -> sem -> ProcessTypeHeaders(class_declaration);
else semantic_environment -> sem -> ProcessTypeHeaders((AstInterfaceDeclaration *) declaration);
}
void TypeSymbol::ProcessMembers()
{
AstClassDeclaration *class_declaration = declaration -> ClassDeclarationCast();
if (class_declaration)
semantic_environment -> sem -> ProcessMembers(class_declaration -> semantic_environment, class_declaration -> class_body);
else semantic_environment -> sem -> ProcessMembers((AstInterfaceDeclaration *) declaration);
}
void TypeSymbol::CompleteSymbolTable()
{
AstClassDeclaration *class_declaration = declaration -> ClassDeclarationCast();
if (class_declaration)
semantic_environment -> sem -> CompleteSymbolTable(class_declaration -> semantic_environment,
class_declaration -> identifier_token, class_declaration -> class_body);
else semantic_environment -> sem -> CompleteSymbolTable((AstInterfaceDeclaration *) declaration);
}
void TypeSymbol::ProcessExecutableBodies()
{
AstClassDeclaration *class_declaration = declaration -> ClassDeclarationCast();
if (class_declaration)
semantic_environment -> sem -> ProcessExecutableBodies(class_declaration -> semantic_environment,
class_declaration -> class_body);
else semantic_environment -> sem -> ProcessExecutableBodies((AstInterfaceDeclaration *) declaration);
}
void TypeSymbol::RemoveCompilationReferences()
{
if (semantic_environment)
{
semantic_environment = NULL;
declaration = NULL;
//
// TODO: What else needs to be reset?
//
if (table)
{
for (int i = 0; i < table -> NumVariableSymbols(); i++)
table -> VariableSym(i) -> declarator = NULL;
for (int j = 0; j < table -> NumMethodSymbols(); j++)
table -> MethodSym(j) -> method_or_constructor_declaration = NULL;
for (int k = 0; k < table -> NumTypeSymbols(); k++)
table -> TypeSym(k) -> declaration = NULL;
for (int l = 0; l < table -> NumAnonymousSymbols(); l++)
table -> AnonymousSym(l) -> declaration = NULL;
}
}
return;
}
TypeSymbol *TypeSymbol::GetArrayType(Semantic *sem, int num_dimensions_)
{
if (num_dimensions_ == 0)
return this;
if (num_dimensions_ < NumArrays())
return Array(num_dimensions_);
if (NumArrays() == 0)
AddArrayType(this);
TypeSymbol *previous_array_type = Array(array -> Length() - 1);
wchar_t *name = new wchar_t[this -> ExternalNameLength() + (num_dimensions_ * 2) + 1];
wcscpy(name, previous_array_type -> ExternalName());
for (int num = array -> Length(), len = previous_array_type -> ExternalNameLength() + 2;
num <= num_dimensions_;
num++, len = len + 2)
{
wcscat(name, StringConstant::US__LB__RB_);
NameSymbol *name_sym = sem -> control.FindOrInsertName(name, len);
AccessFlags acc_flags;
acc_flags.SetACC_PUBLIC();
acc_flags.SetACC_FINAL();
TypeSymbol *type = new TypeSymbol(name_sym);
type -> MarkHeaderProcessed();
type -> MarkConstructorMembersProcessed();
type -> MarkMethodMembersProcessed();
type -> MarkFieldMembersProcessed();
type -> MarkLocalClassProcessingCompleted();
type -> MarkSourceNoLongerPending();
type -> outermost_type = type;
type -> SetFlags(acc_flags);
type -> super = sem -> control.Object();
//
// All arrays implement the interfaces java.io.Serializable and
// java.io.Cloneable
//
if (sem -> control.option.one_one)
type -> AddInterface(sem -> control.Serializable());
type -> AddInterface(sem -> control.Cloneable());
type -> base_type = this;
type -> num_dimensions = num;
type -> SetOwner(this -> ContainingPackage());
type -> table = new SymbolTable(3); // only 2 elements will be added to this table
type -> SetSignature(sem -> control);
MethodSymbol *method = type -> InsertMethodSymbol(sem -> control.clone_name_symbol);
method -> SetType(sem -> control.Object());
method -> SetContainingType(type);
method -> SetFlags(acc_flags);
method -> SetBlockSymbol(new BlockSymbol(1)); // the associated symbol table will remain empty
VariableSymbol *symbol = type -> InsertVariableSymbol(sem -> control.length_name_symbol);
symbol -> SetFlags(acc_flags);
symbol -> SetOwner(type);
symbol -> SetType(sem -> control.int_type);
type -> CompressSpace(); // space optimization
AddArrayType(type);
}
delete [] name;
return Array(num_dimensions_);
}
void TypeSymbol::SetLocation()
{
if (! declaration)
file_location = new FileLocation(file_symbol);
else
{
AstClassDeclaration *class_declaration = declaration -> ClassDeclarationCast();
AstInterfaceDeclaration *interface_declaration = declaration -> InterfaceDeclarationCast();
file_location = new FileLocation(semantic_environment -> sem -> lex_stream,
(class_declaration
? class_declaration -> identifier_token
: (interface_declaration
? interface_declaration -> identifier_token
: ((AstClassInstanceCreationExpression *) declaration)
-> class_body_opt -> left_brace_token)));
}
return;
}
void TypeSymbol::SetSignature(Control &control)
{
if (this -> num_dimensions > 0)
{
char *type_signature;
TypeSymbol *subtype = this -> ArraySubtype();
int signature_len = strlen(subtype -> SignatureString()) + 1; // +1 for '['
type_signature = new char[signature_len + 1]; // +1 for '\0'
type_signature[0] = U_LEFT_BRACKET;
strcpy(type_signature + 1, subtype -> SignatureString());
this -> signature = control.Utf8_pool.FindOrInsert(type_signature, signature_len);
this -> fully_qualified_name = this -> signature;
delete [] type_signature;
}
else
{
wchar_t *package_name = this -> ContainingPackage() -> PackageName();
wchar_t *type_name = this -> ExternalName();
int len = this -> ContainingPackage() -> PackageNameLength() +
this -> ExternalNameLength() + 4; // +1 for 'L' +1 for '/' +1 for ';' +1 for '\0'
wchar_t *type_signature = new wchar_t[len];
wcscpy(type_signature, StringConstant::US_L);
if (this -> ContainingPackage() -> PackageNameLength() > 0 && wcscmp(package_name, StringConstant::US__DO_) != 0)
{
wcscat(type_signature, package_name);
wcscat(type_signature, StringConstant::US__SL_);
}
wcscat(type_signature, type_name);
this -> fully_qualified_name = control.ConvertUnicodeToUtf8(type_signature + 1); // +1 to skip the initial L'L'
wcscat(type_signature, StringConstant::US__SC_);
this -> signature = control.ConvertUnicodeToUtf8(type_signature);
delete [] type_signature;
}
return;
}
int SymbolTable::primes[] = {DEFAULT_HASH_SIZE, 101, 401, MAX_HASH_SIZE};
void SymbolTable::Rehash()
{
hash_size = primes[++prime_index];
delete [] base;
base = (Symbol **) memset(new Symbol *[hash_size], 0, hash_size * sizeof(Symbol *));
int k;
for (k = 0; k < NumTypeSymbols(); k++)
{
TypeSymbol *symbol = TypeSym(k);
int i = symbol -> name_symbol -> index % hash_size;
symbol -> next = base[i];
base[i] = symbol;
}
for (k = 0; k < NumMethodSymbols(); k++)
{
MethodSymbol *symbol = MethodSym(k);
if (symbol -> next != symbol) // not an overload
{
int i = symbol -> name_symbol -> index % hash_size;
symbol -> next = base[i];
base[i] = symbol;
}
}
for (k = 0; k < NumVariableSymbols(); k++)
{
VariableSymbol *symbol = VariableSym(k);
int i = symbol -> name_symbol -> index % hash_size;
symbol -> next = base[i];
base[i] = symbol;
}
for (k = 0; k < NumOtherSymbols(); k++)
{
Symbol *symbol = OtherSym(k);
if (! symbol -> BlockCast())
{
int i = symbol -> Identity() -> index % hash_size;
symbol -> next = base[i];
base[i] = symbol;
}
}
return;
}
SymbolTable::SymbolTable(int hash_size_) : anonymous_symbol_pool(NULL),
type_symbol_pool(NULL),
method_symbol_pool(NULL),
variable_symbol_pool(NULL),
other_symbol_pool(NULL),
constructor(NULL)
{
hash_size = (hash_size_ <= 0 ? 1 : hash_size_);
prime_index = -1;
do
{
if (hash_size < primes[prime_index + 1])
break;
prime_index++;
} while (primes[prime_index] < MAX_HASH_SIZE);
base = (Symbol **) memset(new Symbol *[hash_size], 0, hash_size * sizeof(Symbol *));
}
SymbolTable::~SymbolTable()
{
/*
int n;
int num_slots = 0;
int total = 0;
for (n = 0; n < hash_size; n++)
{
int num = 0;
for (Symbol *s = base[n]; s; s = s -> next)
num++;
if (num > 0)
{
num_slots++;
total += num;
}
}
if (num_slots > 0)
{
cout << "\nDestroying a symbol table with base size " << hash_size << " containing " << num_slots << " non-empty slots\n";
for (n = 0; n < hash_size; n++)
{
int num = 0;
for (Symbol *s = base[n]; s; s = s -> next)
num++;
if (num > 0)
cout << " slot " << n << " contains " << num << " element(s)\n";
}
}
if (hash_size < total)
total = total;
*/
for (int i = 0; i < NumAnonymousSymbols(); i++)
delete AnonymousSym(i);
delete anonymous_symbol_pool;
for (int j = 0; j < NumTypeSymbols(); j++)
delete TypeSym(j);
delete type_symbol_pool;
for (int k = 0; k < NumMethodSymbols(); k++)
delete MethodSym(k);
delete method_symbol_pool;
for (int l = 0; l < NumVariableSymbols(); l++)
delete VariableSym(l);
delete variable_symbol_pool;
for (int m = 0; m < NumOtherSymbols(); m++)
delete OtherSym(m);
delete other_symbol_pool;
delete [] base;
return;
}
PackageSymbol::~PackageSymbol()
{
delete [] package_name;
delete table;
}
void PackageSymbol::SetPackageName()
{
this -> package_name_length = (owner ? owner -> PackageNameLength() + 1 : 0) + NameLength(); // +1 for '/'
this -> package_name = new wchar_t[package_name_length + 1]; // +1 for '\0'
if (owner)
{
wcscpy(this -> package_name, owner -> PackageName());
wcscat(this -> package_name, StringConstant::US__SL_);
}
else this -> package_name[0] = U_NULL;
wcscat(this -> package_name, this -> Name());
assert(wcslen(this -> package_name) == this -> package_name_length);
return;
}
TypeSymbol::TypeSymbol(NameSymbol *name_symbol_) : semantic_environment(NULL),
declaration(NULL),
file_symbol(NULL),
file_location(NULL),
name_symbol(name_symbol_),
external_name_symbol(NULL),
owner(NULL),
outermost_type(NULL),
super(NULL),
base_type(NULL),
index(CycleChecker::OMEGA),
incremental_index(CycleChecker::OMEGA),
status(0),
local(NULL),
non_local(NULL),
supertypes_closure(NULL),
subtypes(NULL),
subtypes_closure(NULL),
innertypes_closure(NULL),
dependents(new SymbolSet()),
parents(new SymbolSet()),
dependents_closure(NULL),
parents_closure(NULL),
num_dimensions(0),
class_literal_class(NULL),
class_literal_method(NULL),
static_initializer_method(NULL),
block_initializer_method(NULL),
signature(NULL),
fully_qualified_name(NULL),
class_literal_name(NULL),
table(NULL),
expanded_type_table(NULL),
expanded_field_table(NULL),
expanded_method_table(NULL),
package(NULL),
class_name(NULL),
local_constructor_call_environments(NULL),
private_access_methods(NULL),
private_access_constructors(NULL),
constructor_parameters(NULL),
generated_constructors(NULL),
enclosing_instances(NULL),
class_literals(NULL),
nested_types(NULL),
interfaces(NULL),
anonymous_types(NULL),
array(NULL),
nested_type_signatures(NULL)
{
Symbol::_kind = TYPE;
}
TypeSymbol::~TypeSymbol()
{
delete semantic_environment;
delete local;
delete non_local;
delete supertypes_closure;
delete subtypes;
delete subtypes_closure;
delete innertypes_closure;
delete dependents;
delete parents;
delete table;
delete expanded_type_table;
delete expanded_field_table;
delete expanded_method_table;
delete file_location;
delete [] class_name;
for (int i = 1; i < NumArrays(); i++)
delete Array(i);
for (int k = 0; k < NumNestedTypeSignatures(); k++)
delete [] NestedTypeSignature(k);
delete nested_type_signatures;
delete local_constructor_call_environments;
delete private_access_methods;
delete private_access_constructors;
delete constructor_parameters;
delete generated_constructors;
delete enclosing_instances;
delete class_literals;
delete nested_types;
delete interfaces;
delete anonymous_types;
delete array;
}
MethodSymbol::~MethodSymbol()
{
for (int i = 0; i < NumThrowsSignatures(); i++)
delete [] ThrowsSignature(i);
delete throws_signatures;
delete formal_parameters;
delete throws;
delete initializer_constructors;
delete block_symbol; // overload(s)
delete [] header;
}
BlockSymbol::BlockSymbol(int hash_size) : table(hash_size > 0 ? new SymbolTable(hash_size) : (SymbolTable *) NULL),
max_variable_index(-1),
try_variable_index(0)
{
Symbol::_kind = BLOCK;
}
BlockSymbol::~BlockSymbol()
{
delete table;
}
PathSymbol::PathSymbol(NameSymbol *name_symbol_) : name_symbol(name_symbol_),
zipfile(NULL)
{
Symbol::_kind = PATH;
}
PathSymbol::~PathSymbol()
{
if (zipfile)
delete zipfile;
}
DirectorySymbol::DirectorySymbol(NameSymbol *name_symbol_, Symbol *owner_) : name_symbol(name_symbol_),
owner(owner_),
mtime(0),
table(NULL),
directory_name(NULL),
entries(NULL)
{
Symbol::_kind = _DIRECTORY;
}
DirectorySymbol::~DirectorySymbol()
{
delete [] directory_name;
delete entries;
delete table;
}
void DirectorySymbol::SetDirectoryName()
{
PathSymbol *path_symbol = owner -> PathCast();
if (path_symbol)
{
if (strcmp(path_symbol -> Utf8Name(), StringConstant::U8S__DO_) == 0)
{
this -> directory_name_length = this -> Utf8NameLength();
this -> directory_name = new char[this -> directory_name_length + 1]; // +1 for '\0'
strcpy(this -> directory_name, this -> Utf8Name());
}
else
{
this -> directory_name_length = path_symbol -> Utf8NameLength();
this -> directory_name = new char[this -> directory_name_length + 1]; // +1 for '\0'
strcpy(this -> directory_name, path_symbol -> Utf8Name());
}
}
else
{
DirectorySymbol *owner_directory = owner -> DirectoryCast();
if (this -> Name()[this -> NameLength() - 1] == U_SLASH || // An absolute file name ?
strcmp(owner_directory -> DirectoryName(), StringConstant::U8S__DO_) == 0) // or is the owner "." ?
{
this -> directory_name_length = this -> Utf8NameLength();
this -> directory_name = new char[this -> directory_name_length + 1]; // +1 for '\0'
strcpy(this -> directory_name, this -> Utf8Name());
}
else
{
int owner_length = owner_directory -> DirectoryNameLength();
char *owner_name = owner_directory -> DirectoryName();
this -> directory_name_length = owner_length +
this -> Utf8NameLength() +
(owner_name[owner_length - 1] != U_SLASH ? 1 : 0); // +1 for '/'
this -> directory_name = new char[this -> directory_name_length + 1]; // +1 for '\0'
strcpy(this -> directory_name, owner_directory -> DirectoryName());
if (owner_name[owner_length - 1] != U_SLASH)
strcat(this -> directory_name, StringConstant::U8S__SL_);
strcat(this -> directory_name, this -> Utf8Name());
}
}
assert(strlen(this -> directory_name) == this -> directory_name_length);
return;
}
void DirectorySymbol::ResetDirectory()
{
assert(! this -> IsZip());
//
// TODO: the stat function does not work for directories in that the "modified" time stamp associated
// with a directory is not updated when a file contained in the directory is changed.
// For now, we always reread the directory.
//
// struct stat status;
// if ((::SystemStat(this -> DirectoryName(), &status) == 0) && status.st_mtime > mtime)
// {
// this -> mtime = status.st_mtime;
//
// delete this -> entries;
// this -> entries = new DirectoryTable();
//
// ReadDirectory();
// }
//
// else if (! entries) // if we cannot read the directory, allocate a default directory.
// this -> entries = new DirectoryTable();
//
delete this -> entries;
this -> entries = new DirectoryTable();
ReadDirectory();
return;
}
void DirectorySymbol::ReadDirectory()
{
#if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
DIR *directory = opendir(this -> DirectoryName());
if (directory)
{
for (dirent *entry = readdir(directory); entry; entry = readdir(directory))
{
int length = strlen(entry -> d_name);
//
// Check if the file is a java source, a java class file or a subdirectory.
// Since packages cannot start with '.', we skip all files that start with
// a dot. That includes this directory "." and its parent ".."
//
if ((length > FileSymbol::java_suffix_length &&
FileSymbol::IsJavaSuffix(&entry -> d_name[length - FileSymbol::java_suffix_length])) ||
(length > FileSymbol::class_suffix_length &&
FileSymbol::IsClassSuffix(&entry -> d_name[length - FileSymbol::class_suffix_length])) ||
((Case::Index(entry -> d_name, U_DOT) < 0) && SystemIsDirectory(entry -> d_name)))
entries -> InsertEntry((DirectorySymbol *) this, entry -> d_name, length);
}
closedir(directory);
}
#elif defined(WIN32_FILE_SYSTEM)
char *directory_name = new char[this -> DirectoryNameLength() + 3]; // +2 for "/*" +1 for '\0'
strcpy(directory_name, this -> DirectoryName());
if (directory_name[this -> DirectoryNameLength() - 1] != U_SLASH)
strcat(directory_name, StringConstant::U8S__SL_);
strcat(directory_name, StringConstant::U8S__ST_);
WIN32_FIND_DATA entry;
HANDLE file_handle = FindFirstFile(directory_name, &entry);
if (file_handle != INVALID_HANDLE_VALUE)
{
do
{
int length = strlen(entry.cFileName);
//
// Check if the file is a java source, a java class file or a subdirectory.
// Since packages cannot start with '.', we skip all files that start with
// a dot. That includes this directory "." and its parent ".."
//
bool is_java = (length > FileSymbol::java_suffix_length &&
FileSymbol::IsJavaSuffix(&entry.cFileName[length - FileSymbol::java_suffix_length])),
is_class = (length > FileSymbol::class_suffix_length &&
FileSymbol::IsClassSuffix(&entry.cFileName[length - FileSymbol::class_suffix_length]));
if (is_java ||
is_class ||
(entry.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && Case::Index(entry.cFileName, U_DOT) < 0))
{
char *clean_name = new char[length + 1];
for (int i = 0; i < length; i++)
clean_name[i] = (entry.cFileName[i] == U_BACKSLASH ? U_SLASH : entry.cFileName[i]);
if (is_java)
strcpy(&clean_name[length - FileSymbol::java_suffix_length], FileSymbol::java_suffix);
else if (is_class)
strcpy(&clean_name[length - FileSymbol::class_suffix_length], FileSymbol::class_suffix);
DirectoryEntry *entry = entries -> InsertEntry((DirectorySymbol *) this, clean_name, length);
if (! is_java)
entries -> InsertCaseInsensitiveEntry(entry);
delete [] clean_name;
}
} while (FindNextFile(file_handle, &entry));
FindClose(file_handle);
}
delete [] directory_name;
#endif
return;
}
DirectorySymbol *FileSymbol::OutputDirectory()
{
return (output_directory ? output_directory : output_directory = Control::GetOutputDirectory(this));
}
void FileSymbol::SetFileName()
{
PathSymbol *path_symbol = this -> PathSym();
char *directory_name = directory_symbol -> DirectoryName();
int directory_name_length = directory_symbol -> DirectoryNameLength();
bool dot_directory = (strcmp(directory_name, StringConstant::U8S__DO_) == 0);
this -> file_name_length = (dot_directory ? 0 : directory_name_length) +
this -> Utf8NameLength() +
(path_symbol -> IsZip() // For zip files we need "()" for regular directory, we need 1 '/'
? 2
: (dot_directory || directory_name[directory_name_length - 1] == U_SLASH ? 0 : 1)) +
(kind == JAVA ? java_suffix_length : class_suffix_length);
file_name = new char[file_name_length + 1]; // +1 for '\0'
if (dot_directory)
file_name[0] = U_NULL;
else
{
strcpy(file_name, directory_symbol -> DirectoryName());
if (path_symbol -> IsZip())
strcat(file_name, StringConstant::U8S__LP_);
else if (directory_name[directory_name_length - 1] != U_SLASH)
strcat(file_name, StringConstant::U8S__SL_);
}
strcat(file_name, this -> Utf8Name());
strcat(file_name, kind == JAVA ? FileSymbol::java_suffix : FileSymbol::class_suffix);
if (path_symbol -> IsZip())
strcat(file_name, StringConstant::U8S__RP_);
assert(strlen(this -> file_name) == this -> file_name_length);
return;
}
void FileSymbol::CleanUp()
{
delete lex_stream;
lex_stream = NULL;
if (compilation_unit)
{
delete compilation_unit -> ast_pool;
compilation_unit = NULL;
}
delete semantic;
semantic = NULL;
return;
}
void TypeSymbol::SetClassName()
{
int length;
if (semantic_environment -> sem -> control.option.directory)
{
DirectorySymbol *output_directory = file_symbol -> OutputDirectory();
int directory_length = output_directory -> DirectoryNameLength();
char *directory_name = output_directory -> DirectoryName();
length = directory_length + this -> ExternalUtf8NameLength() + FileSymbol::class_suffix_length + 1; // +1 for /
class_name = new char[length + 1]; // +1 for '\0'
strcpy(class_name, directory_name);
if (directory_name[directory_length - 1] != U_SLASH)
strcat(class_name, StringConstant::U8S__SL_);
}
else
{
char *file_name = semantic_environment -> sem -> lex_stream -> FileName();
int n;
for (n = semantic_environment -> sem -> lex_stream -> FileNameLength() - 1; n >= 0; n--)
{
if (file_name[n] == U_SLASH)
break;
}
n++;
length = n + this -> ExternalUtf8NameLength() + FileSymbol::class_suffix_length;
class_name = new char[length + 1]; // +1 for '\0'
strncpy(class_name, file_name, n);
class_name[n] = U_NULL;
}
strcat(class_name, ExternalUtf8Name());
strcat(class_name, FileSymbol::class_suffix);
assert(strlen(this -> class_name) <= length);
return;
}
void TypeSymbol::ProcessNestedTypeSignatures(Semantic *sem, LexStream::TokenIndex tok)
{
for (int i = 0; i < NumNestedTypeSignatures(); i++)
{
int length = strlen(NestedTypeSignature(i));
wchar_t *nested_class_name = new wchar_t[length + 1];
sem -> ConvertUtf8ToUnicode(nested_class_name, NestedTypeSignature(i), length);
NameSymbol *name_symbol = sem -> control.FindOrInsertName(nested_class_name, length);
delete [] nested_class_name;
delete [] NestedTypeSignature(i);
sem -> ProcessNestedType(this, name_symbol, tok);
}
delete nested_type_signatures;
nested_type_signatures = NULL;
return;
}
void MethodSymbol::ProcessMethodThrows(Semantic *sem, LexStream::TokenIndex tok)
{
if (throws_signatures)
{
assert(sem);
//
// Process throws clause
//
for (int i = 0; i < NumThrowsSignatures(); i++)
{
int length = strlen(ThrowsSignature(i));
wchar_t *type_name = new wchar_t[length + 1];
sem -> ConvertUtf8ToUnicode(type_name, ThrowsSignature(i), length);
this -> AddThrows(sem -> ReadType(this -> containing_type, type_name, tok));
delete [] type_name;
delete [] ThrowsSignature(i);
}
delete throws_signatures;
throws_signatures = NULL;
}
return;
}
void MethodSymbol::SetSignature(Control &control, VariableSymbol *this0_variable)
{
int len = 2 + strlen(this -> Type() -> SignatureString()); // +1 for '(' +1 for ')'
if (this0_variable)
len += strlen(this0_variable -> Type() -> SignatureString());
for (int i = 0; i < this -> NumFormalParameters(); i++)
{
TypeSymbol *formal_type = this -> FormalParameter(i) -> Type();
len += strlen(formal_type -> SignatureString());
}
char *method_signature = new char[len + 1]; // +1 for '\0'
method_signature[0] = U_LEFT_PARENTHESIS;
int k = 1;
if (this0_variable)
{
for (char *str = this0_variable -> Type() -> SignatureString(); *str; str++, k++)
method_signature[k] = *str;
}
for (int j = 0; j < this -> NumFormalParameters(); j++)
{
TypeSymbol *formal_type = this -> FormalParameter(j) -> Type();
for (char *str = formal_type -> SignatureString(); *str; str++, k++)
method_signature[k] = *str;
}
method_signature[k++] = U_RIGHT_PARENTHESIS;
for (char *str = this -> Type() -> SignatureString(); *str; str++, k++)
method_signature[k] = *str;
method_signature[k] = U_NULL;
this -> signature = control.Utf8_pool.FindOrInsert(method_signature, len);
delete [] method_signature;
return;
}
void MethodSymbol::ProcessMethodSignature(Semantic *sem, LexStream::TokenIndex token_location)
{
if (! this -> type_)
{
assert(sem);
int num_parameters = 0;
char *signature = this -> SignatureString();
signature++; // +1 to skip initial '('
//
// For the constructor of an inner type, skip the "this$0" argument.
//
if (this -> containing_type -> IsInner() && this -> Identity() == sem -> control.init_name_symbol)
{
if (*signature != U_RIGHT_PARENTHESIS)
{
//
// Move to next signature
//
char *str;
for (str = signature; *str == U_LEFT_BRACKET; str++)
;
if (*str == U_L)
{
for (str++; *str != U_SEMICOLON; str++)
;
}
int len = str - signature + 1;
signature += len; // make signature point to next type
}
}
while (*signature != U_RIGHT_PARENTHESIS)
{
//
// Make up a name for each parameter... Recall that for an inner class we need to skip the this$0 parameter
//
NameSymbol *name_symbol = sem -> control.MakeParameter(++num_parameters);
VariableSymbol *symbol = new VariableSymbol(name_symbol);
symbol -> SetType(sem -> ProcessSignature(this -> containing_type, signature, token_location));
symbol -> MarkComplete();
this -> AddFormalParameter(symbol);
//
// Move to next signature
//
char *str;
for (str = signature; *str == U_LEFT_BRACKET; str++)
;
if (*str == U_L)
{
for (str++; *str != U_SEMICOLON; str++)
;
}
int len = str - signature + 1;
signature += len; // make signature point to next type
}
signature++; // skip L')'
//
// Now set the type of the method.
//
this -> SetType(sem -> ProcessSignature(this -> containing_type, signature, token_location));
//
// Create a symbol table for this method for consistency... and in order
// to release the space used by the variable paramaters later.
//
BlockSymbol *block_symbol = new BlockSymbol(num_parameters);
for (int k = 0; k < num_parameters; k++)
block_symbol -> InsertVariableSymbol((*this -> formal_parameters)[k]);
block_symbol -> CompressSpace(); // space optimization
this -> SetBlockSymbol(block_symbol);
}
return;
}
void MethodSymbol::CleanUp()
{
BlockSymbol *block_symbol = new BlockSymbol(this -> NumFormalParameters());
//
// Make a copy of each parameter into the new pared-down symbol table and
// fix the FormalParameter information to identify the new symbol.
//
for (int k = 0; k < this -> NumFormalParameters(); k++)
{
VariableSymbol *formal_parameter = (*formal_parameters)[k],
*symbol = block_symbol -> InsertVariableSymbol(formal_parameter -> Identity());
symbol -> SetType(formal_parameter -> Type());
symbol -> MarkComplete();
(*formal_parameters)[k] = symbol;
}
//
// Destroy the old symbol and replace it by the new one.
//
delete this -> block_symbol;
block_symbol -> CompressSpace(); // space optimization
this -> SetBlockSymbol(block_symbol);
this -> method_or_constructor_declaration = NULL; // remove reference to Ast structure
return;
}
void VariableSymbol::ProcessVariableSignature(Semantic *sem, LexStream::TokenIndex token_location)
{
if (! this -> type_)
{
assert(sem);
this -> SetType(sem -> ProcessSignature((TypeSymbol *) owner, signature_string, token_location));
}
return;
}
bool TypeSymbol::IsNestedIn(TypeSymbol *type)
{
for (SemanticEnvironment *env = this -> semantic_environment; env != NULL; env = env -> previous)
{
if (env -> Type() == type)
return true;
}
return false;
}
bool TypeSymbol::CanAccess(TypeSymbol *type)
{
assert(semantic_environment);
SemanticEnvironment *env = this -> semantic_environment;
//
// Note that this case is only possible in the current environment (i.e., it is not recursively applicable)
// as it is not possible to declare an inner class (even an anonymous one) within an explicit
// constructor invocation. This is the case precisely because of the unavailability of the "this"
// which one would need to pass to the inner class in question. See comment below...
//
if (env -> explicit_constructor_invocation && env -> explicit_constructor_invocation -> SuperCallCast())
{
//
// If we are processing a super call statement in the constructor of an inner class then
// we have access to the this$0 (passed to the constructor of the inner class as parameter) but
// not to the "this" of the inner class in question, unless it is static.
//
if (this -> IsSubclass(type))
return this -> ACC_STATIC(); // "this" class is accessible only if it is static.
if (this -> IsInner())
{
if (this -> ContainingType() -> IsSubclass(type))
return true;
env = env -> previous; // skip "this" type.
}
}
for (; env != NULL; env = env -> previous)
{
if (env -> StaticRegion()) // are we in a static environment?
break;
else if (env -> Type() -> IsSubclass(type)) // then, check if we reached the type in question or one of its superclasses;
return true;
else if (env -> Type() -> ACC_STATIC()) // next, check whether or not the current type is static...
break;
}
return false;
}
//
// Given two types T and T2 in different packages, the type T has protected
// access to T2 iff T or any class in which T is lexically enclosed is a subclass
// of T2 or of some other type T3 that lexically encloses T2.
//
// Of course, T2 and all its enclosing classes, if any, must have been declared
// either public or protected, otherwise they could not be eligible as a superclass
// candidate. We do not (and need not) check for that condition here.
//
bool TypeSymbol::HasProtectedAccessTo(TypeSymbol *target_type)
{
assert(semantic_environment);
for (SemanticEnvironment *env = this -> semantic_environment; env != NULL; env = env -> previous)
{
TypeSymbol *main_type = env -> Type();
for (TypeSymbol *type = target_type; type; type = type -> owner -> TypeCast())
{
if (main_type -> IsSubclass(type)) // then, check if we reached the type in question or one of its superclasses;
return true;
}
}
return false;
}
inline NameSymbol *TypeSymbol::GetThisName(Control &control, int n)
{
wchar_t info[12],
*str = &info[11];
*str = U_NULL;
int num = n;
do
{
*--str = (U_0 + num % 10);
num /= 10;
} while (num != 0);
int length = wcslen(StringConstant::US__this_DOLLAR) + (&info[11] - str);
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__this_DOLLAR);
wcscat(name, str);
NameSymbol *name_symbol = control.FindOrInsertName(name, length);
delete [] name;
return name_symbol;
}
VariableSymbol *TypeSymbol::InsertThis(int n)
{
assert(IsInner());
Control &control = semantic_environment -> sem -> control;
VariableSymbol *variable_symbol = NULL;
if (n == 0)
{
assert(NumConstructorParameters() == 0); // no local shadows and no this$0 !!!
assert(NumEnclosingInstances() == 0);
//
// Create a this0 pointer for an inner class.
//
variable_symbol = InsertVariableSymbol(control.this0_name_symbol);
variable_symbol -> MarkSynthetic();
variable_symbol -> SetType(ContainingType());
variable_symbol -> SetACC_PRIVATE();
// variable_symbol -> SetACC_FINAL();
variable_symbol -> SetOwner((TypeSymbol *) this);
variable_symbol -> MarkComplete();
AddConstructorParameter(variable_symbol);
AddEnclosingInstance(variable_symbol); // must at least have this$0
}
else
{
assert(NumEnclosingInstances() == n);
//
// Create a this$n pointer.
//
variable_symbol = InsertVariableSymbol(GetThisName(control, n));
variable_symbol -> MarkSynthetic();
variable_symbol -> SetType(EnclosingInstance(n - 1) -> Type() -> ContainingType());
variable_symbol -> SetACC_PRIVATE();
// variable_symbol -> SetACC_FINAL();
variable_symbol -> SetOwner((TypeSymbol *) this);
variable_symbol -> MarkComplete();
AddEnclosingInstance(variable_symbol);
}
return variable_symbol;
}
TypeSymbol *TypeSymbol::FindOrInsertClassLiteralClass(LexStream::TokenIndex tok)
{
Semantic *sem = semantic_environment -> sem;
AstCompilationUnit *compilation_unit = sem -> compilation_unit;
Control &control = sem -> control;
assert(this == outermost_type);
if (! this -> class_literal_class)
{
AstClassInstanceCreationExpression *class_creation = compilation_unit -> ast_pool -> GenClassInstanceCreationExpression();
class_creation -> base_opt = NULL;
class_creation -> dot_token_opt = 0;
class_creation -> new_token = tok;
AstSimpleName *ast_type= compilation_unit -> ast_pool -> GenSimpleName(tok);
class_creation -> class_type = compilation_unit -> ast_pool -> GenTypeExpression(ast_type);
class_creation -> left_parenthesis_token = tok;
class_creation -> right_parenthesis_token = tok;
AstClassBody *class_body = compilation_unit -> ast_pool -> GenClassBody();
class_body -> left_brace_token = tok;
class_body -> right_brace_token = tok;
class_creation -> class_body_opt = class_body;
TypeSymbol *class_literal_type = sem -> GetAnonymousType(class_creation, control.Object());
(void) class_literal_type -> FindOrInsertClassLiteralMethod(control);
sem -> AddDependence(class_literal_type, control.Class(), tok);
this -> class_literal_class = class_literal_type;
}
return this -> class_literal_class;
}
MethodSymbol *TypeSymbol::FindOrInsertClassLiteralMethod(Control &control)
{
if (! class_literal_method)
{
BlockSymbol *block_symbol = new BlockSymbol(1); // the associated symbol table will contain 1 element
block_symbol -> max_variable_index = 0;
NameSymbol *name_symbol = control.FindOrInsertName(StringConstant::US__class_DOLLAR,
wcslen(StringConstant::US__class_DOLLAR));
class_literal_method = InsertMethodSymbol(name_symbol);
class_literal_method -> SetType(control.Class());
class_literal_method -> SetACC_STATIC();
class_literal_method -> SetContainingType((TypeSymbol *) this);
class_literal_method -> SetBlockSymbol(block_symbol);
VariableSymbol *variable_symbol = block_symbol -> InsertVariableSymbol(control.MakeParameter(1));
variable_symbol -> MarkSynthetic();
variable_symbol -> SetType(control.String());
variable_symbol -> SetOwner(class_literal_method);
variable_symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
class_literal_method -> AddFormalParameter(variable_symbol);
class_literal_method -> SetSignature(control);
}
return class_literal_method;
}
Utf8LiteralValue *TypeSymbol::FindOrInsertClassLiteralName(Control &control)
{
if (! class_literal_name)
{
int length = fully_qualified_name -> length;
char *slashed_name = fully_qualified_name -> value;
char *name = new char[length + 1];
for (int i = 0; i < length; i++)
name[i] = (slashed_name[i] == U_SLASH ? (wchar_t) U_DOT : slashed_name[i]);
name[length] = U_NULL;
class_literal_name = control.Utf8_pool.FindOrInsert(name, length);
delete [] name;
}
return class_literal_name;
}
VariableSymbol *TypeSymbol::FindOrInsertClassLiteral(TypeSymbol *type)
{
assert(IsTopLevel() && (! type -> Primitive()));
Semantic *sem = semantic_environment -> sem;
Control &control = sem -> control;
(void) this -> FindOrInsertClassLiteralMethod(control);
(void) type -> FindOrInsertClassLiteralName(control);
NameSymbol *name_symbol = NULL;
char *signature = type -> SignatureString();
if (signature[0] == U_LEFT_BRACKET) // an array?
{
int array_length = wcslen(StringConstant::US__array),
length = strlen(signature) + array_length;
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__array);
int i,
k;
for (i = 0, k = array_length; signature[i] == U_LEFT_BRACKET; i++, k++)
name[k] = U_DOLLAR;
for (wchar_t ch = signature[i++]; ch && ch != U_SEMICOLON; ch = signature[i++])
name[k++] = (ch == U_SLASH ? (wchar_t) U_DOLLAR : ch);
name[k] = U_NULL;
name_symbol = control.FindOrInsertName(name, k);
delete [] name;
}
else if (signature[0] == U_L) // a reference type ?
{
int class_length = wcslen(StringConstant::US__class_DOLLAR),
length = strlen(signature) + class_length;
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__class_DOLLAR);
int i = 0,
k = class_length;
for (wchar_t ch = signature[i++]; ch && ch != U_SEMICOLON; ch = signature[i++])
name[k++] = (ch == U_SLASH ? (wchar_t) U_DOLLAR : ch);
name[k] = U_NULL;
name_symbol = control.FindOrInsertName(name, k);
delete [] name;
}
VariableSymbol *variable_symbol = FindVariableSymbol(name_symbol);
if (! variable_symbol)
{
variable_symbol = InsertVariableSymbol(name_symbol);
variable_symbol -> MarkSynthetic();
variable_symbol -> SetType(control.Class());
variable_symbol -> SetACC_PRIVATE();
variable_symbol -> SetACC_STATIC();
variable_symbol -> SetOwner((TypeSymbol *) this);
variable_symbol -> MarkComplete();
AddClassLiteral(variable_symbol);
}
return variable_symbol;
}
VariableSymbol *TypeSymbol::FindOrInsertLocalShadow(VariableSymbol *local)
{
assert(this -> IsLocal());
Control &control = semantic_environment -> sem -> control;
VariableSymbol *variable = FindVariableSymbol(local -> Identity());
//
// For a local class, if it does not yet have a shadow for a local variable
// that it needs access to, create one.
//
// Note that since this function is always invoked after the symbol
// table for the type in question has been extended, the local shadow will
// not appear in the expanded_field_table. Creating a shadow in the
// expanded_field_table as well would cut down on the number of calls to
// this function. However, the reason why we don't create such a shadow is
// that since the new symbol is assigned a new name on the fly, its
// name_symbol will fall outside the range of the expanded field table in
// question.
//
if (! variable)
{
variable = InsertVariableSymbol(local -> Identity());
variable -> MarkSynthetic();
variable -> accessed_local = local;
variable -> SetType(local -> Type());
variable -> SetACC_PRIVATE();
// variable -> SetACC_FINAL();
variable -> SetOwner((TypeSymbol *) this);
variable -> MarkComplete();
int length = 4 + local -> NameLength(); // +4 for val$
wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(external_name, StringConstant::US__val_DOLLAR);
wcscat(external_name, local -> Name());
variable -> SetExternalIdentity(control.FindOrInsertName(external_name, length));
AddConstructorParameter(variable);
delete [] external_name;
for (int i = 0; i < NumGeneratedConstructors(); i++)
{
MethodSymbol *constructor = GeneratedConstructor(i);
VariableSymbol *symbol = constructor -> block_symbol -> FindVariableSymbol(local -> Identity());
if (! symbol)
{
symbol = constructor -> block_symbol -> InsertVariableSymbol(local -> Identity());
symbol -> MarkSynthetic();
symbol -> SetType(variable -> Type());
symbol -> SetOwner(constructor);
symbol -> SetExternalIdentity(external_name_symbol);
symbol -> SetLocalVariableIndex(constructor -> block_symbol -> max_variable_index++);
if (symbol -> Type() == control.long_type || symbol -> Type() == control.double_type)
constructor -> block_symbol -> max_variable_index++;
constructor -> AddFormalParameter(symbol);
}
}
}
return variable;
}
MethodSymbol *TypeSymbol::GetReadAccessMethod(MethodSymbol *member)
{
if (! member -> read_method)
{
TypeSymbol *type = member -> containing_type;
Semantic *sem = type -> semantic_environment -> sem;
Control &control = sem -> control;
StoragePool *ast_pool = sem -> compilation_unit -> ast_pool;
wchar_t info[12],
*str = &info[11];
int n = (member -> Identity() == control.init_name_symbol ? type -> NumPrivateAccessConstructors()
: type -> NumPrivateAccessMethods());
*str = U_NULL;
do
{
*--str = (U_0 + n % 10);
n /= 10;
} while (n != 0);
int length = 7 + (&info[11] - str); // +7 for access$
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__access_DOLLAR);
wcscat(name, str);
BlockSymbol *block_symbol = new BlockSymbol(member -> NumFormalParameters() + 3);
MethodSymbol *method = type -> InsertMethodSymbol(control.FindOrInsertName(name, length));
method -> MarkSynthetic();
method -> SetType(member -> Type());
if (member -> ACC_STATIC())
{
method -> SetACC_STATIC();
block_symbol -> max_variable_index = 0;
}
else block_symbol -> max_variable_index = 1;
method -> SetContainingType(type);
method -> SetBlockSymbol(block_symbol);
for (int i = 0; i < member -> NumThrows(); i++)
method -> AddThrows(member -> Throws(i));
//
//
//
if (member -> Identity() != control.init_name_symbol) // not a constructor
{
for (int i = 0; i < member -> NumFormalParameters(); i++)
{
VariableSymbol *parm = method -> block_symbol -> InsertVariableSymbol(member -> FormalParameter(i) -> Identity());
parm -> MarkSynthetic();
parm -> SetType(member -> FormalParameter(i) -> Type());
parm -> SetOwner(method);
parm -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
if (parm -> Type() == control.long_type || parm -> Type() == control.double_type)
block_symbol -> max_variable_index++;
method -> AddFormalParameter(parm);
}
method -> SetSignature(control);
// A read access method has no throws clause !
type -> AddPrivateAccessMethod(method);
}
else
{
method -> SetExternalIdentity(member -> Identity());
Ast *declaration = member -> method_or_constructor_declaration;
AstMethodDeclaration *method_declaration = declaration -> MethodDeclarationCast();
AstMethodDeclarator *declarator = (method_declaration
? method_declaration -> method_declarator
: ((AstConstructorDeclaration *) declaration) -> constructor_declarator);
LexStream::TokenIndex loc = declarator -> identifier_token;
AstMethodDeclarator *method_declarator = ast_pool -> GenMethodDeclarator();
method_declarator -> identifier_token = loc;
method_declarator -> left_parenthesis_token = declarator -> LeftToken();
method_declarator -> right_parenthesis_token = declarator -> RightToken();
AstThisCall *this_call = ast_pool -> GenThisCall();
this_call -> base_opt = NULL;
this_call -> this_token = loc;
this_call -> left_parenthesis_token = loc;
this_call -> right_parenthesis_token = loc;
this_call -> semicolon_token = loc;
this_call -> symbol = member;
VariableSymbol *this0_variable = NULL;
if (type -> IsInner())
{
this0_variable = block_symbol -> InsertVariableSymbol(control.this0_name_symbol);
this0_variable -> MarkSynthetic();
this0_variable -> SetType(type -> ContainingType());
this0_variable -> SetOwner(method);
this0_variable -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
}
for (int i = 0; i < member -> NumFormalParameters(); i++)
{
VariableSymbol *parm = method -> block_symbol -> InsertVariableSymbol(member -> FormalParameter(i) -> Identity());
parm -> MarkSynthetic();
parm -> SetType(member -> FormalParameter(i) -> Type());
parm -> SetOwner(method);
parm -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
if (parm -> Type() == control.long_type || parm -> Type() == control.double_type)
block_symbol -> max_variable_index++;
method -> AddFormalParameter(parm);
//
// Since private_access_constructors will compiled (see body.cpp), we must create
// valid ast_simple_names for its parameters.
//
AstVariableDeclaratorId *variable_declarator_name = declarator -> FormalParameter(i) -> variable_declarator_name;
AstSimpleName *simple_name = ast_pool -> GenSimpleName(variable_declarator_name -> identifier_token);
simple_name -> symbol = parm;
this_call -> AddArgument(simple_name);
}
method -> SetSignature(control, this0_variable);
// A read access method has no throws clause !
AstReturnStatement *return_statement = ast_pool -> GenReturnStatement();
return_statement -> return_token = loc;
return_statement -> expression_opt = NULL;
return_statement -> semicolon_token = loc;
return_statement -> is_reachable = true;
AstBlock *block = ast_pool -> GenBlock();
block -> AllocateBlockStatements(1); // this block contains one statement
block -> left_brace_token = loc;
block -> right_brace_token = loc;
block -> is_reachable = true;
block -> can_complete_normally = false;
block -> AddStatement(return_statement);
AstConstructorBlock *constructor_block = ast_pool -> GenConstructorBlock();
constructor_block -> left_brace_token = loc;
constructor_block -> explicit_constructor_invocation_opt = this_call;
constructor_block -> block = block;
constructor_block -> right_brace_token = loc;
AstConstructorDeclaration *constructor_declaration = ast_pool -> GenConstructorDeclaration();
constructor_declaration -> constructor_declarator = method_declarator;
constructor_declaration -> constructor_body = constructor_block;
constructor_declaration -> constructor_symbol = method;
method -> method_or_constructor_declaration = constructor_declaration;
if (type -> IsLocal())
sem -> GenerateLocalConstructor(method);
type -> AddPrivateAccessConstructor(method);
}
method -> accessed_member = member;
member -> read_method = method;
delete [] name;
}
return member -> read_method;
}
MethodSymbol *TypeSymbol::GetReadAccessMethod(VariableSymbol *member)
{
if (! member -> read_method)
{
TypeSymbol *type = member -> owner -> TypeCast();
Semantic *sem = type -> semantic_environment -> sem;
Control &control = sem -> control;
wchar_t info[12],
*str = &info[11];
int n = type -> NumPrivateAccessMethods();
*str = U_NULL;
do
{
*--str = (U_0 + n % 10);
n /= 10;
} while (n != 0);
int length = 7 + (&info[11] - str); // +7 for access$
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__access_DOLLAR);
wcscat(name, str);
MethodSymbol *method = type -> InsertMethodSymbol(control.FindOrInsertName(name, length));
method -> MarkSynthetic();
method -> SetType(member -> Type());
if (member -> ACC_STATIC())
method -> SetACC_STATIC();
method -> SetContainingType(type);
// No block_symbol is associated with an access method !
// A read access method for a field has no formal parameters !
method -> SetSignature(control);
// A read access method has no throws clause !
method -> accessed_member = member;
member -> read_method = method;
type -> AddPrivateAccessMethod(method);
delete [] name;
}
return member -> read_method;
}
MethodSymbol *TypeSymbol::GetWriteAccessMethod(VariableSymbol *member)
{
if (! member -> write_method)
{
TypeSymbol *type = member -> owner -> TypeCast();
Semantic *sem = type -> semantic_environment -> sem;
Control &control = sem -> control;
wchar_t info[12],
*str = &info[11];
int n = type -> NumPrivateAccessMethods();
*str = U_NULL;
do
{
*--str = (U_0 + n % 10);
n /= 10;
} while (n != 0);
int length = 7 + (&info[11] - str); // +7 for access$
wchar_t *name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(name, StringConstant::US__access_DOLLAR);
wcscat(name, str);
MethodSymbol *method = type -> InsertMethodSymbol(control.FindOrInsertName(name, length));
method -> MarkSynthetic();
method -> SetType(sem -> control.void_type);
if (member -> ACC_STATIC())
method -> SetACC_STATIC();
method -> SetContainingType(type);
method -> SetBlockSymbol(new BlockSymbol(3)); // the associated symbol table will contain 1 element
//
// A write access method takes exactly one argument of the same type
// as the variable. For a member named "m", its body will consist of
// the single statement:
//
// this.m = m;
//
VariableSymbol *symbol = method -> block_symbol -> InsertVariableSymbol(member -> Identity());
symbol -> MarkSynthetic();
symbol -> SetType(member -> Type());
method -> AddFormalParameter(symbol);
method -> SetSignature(control);
// A write access method has no throws clause !
method -> accessed_member = member;
member -> write_method = method;
type -> AddPrivateAccessMethod(method);
delete [] name;
}
return member -> write_method;
}